import ipfshttpclient
import os.path, sys
import yaml
from myutils import *
from mydefine import *
from sqltb import *
from model_parser import *
from concurrent.futures import ThreadPoolExecutor, wait
import ipfshttpclient
import json
import multiprocessing


def search_text(head_recved, db):
    cmd = 'select hash,extend from tb_model where name = "%s"' % (head_recved["text"])
    status, rows = db.sqlexe(cmd)
    if status != None:
        return {"type": RESPONSE_ERROR, "status": status}
    if len(rows) == 0:
        return {"type": RESPONSE_SEARCH_TEXT, "status": "No matching model found"}
    with open('config.yml', 'r') as conf_file:
        ymlConf = yaml.load(conf_file, Loader= yaml.FullLoader)
        ipfs_url = ymlConf['ipfs']['url']
    try:
        client = ipfshttpclient.connect(ipfs_url)
        (hash,extend) = rows[0]
        path = os.path.abspath(f'cache/{hash}.{extend}')
        if not os.path.exists(path):
            result = client.cat(hash)
            with open(path,'wb') as cfile:
                cfile.write(result)
                cfile.flush()
    except Exception as e:
        logger.error(e)
        return {"type": RESPONSE_ERROR, "status": str(e)}
    head_tosend = {"type": RESPONSE_SEARCH_TEXT, "status": "", "path": path}
    logger.info("RESPONSE_SEARCH_TEXT Send: %s" % head_tosend)
    return head_tosend


def search_file(head_recved, fnet, db):
    # 获取模型数据
    modelFilePath = head_recved['file']
    models = []
    
    with open('config.yml', 'r') as conf_file:
        ymlConf = yaml.load(conf_file, Loader= yaml.FullLoader)
        ipfs_url = ymlConf['ipfs']['url']
    tb_model = TBModel(database=db, feature_net=fnet, ipfs_url=ipfs_url)
    try:
        points_list=pcd2plist(mesh2pcd(modelFilePath))
        points = torch.tensor(list(points_list), dtype=torch.float).view(1, -1, 3)
        status, models = tb_model.search_by_feature(points=points, category=None)
    except Exception as e:
        status = str(e)
        logger.warning(f'Failed to extract features of "{modelFilePath}", info: {status}')

    if(None != status):
        head_tosend = {"type": RESPONSE_ERROR, "status":status}
    else:
        if len(models['values']) > 0:
            head_tosend = {"type": RESPONSE_SEARCH_FILE, "status":'', "path": models['values'][0][4]}
            logger.info("Path: %s" % models['values'][0][4])
        else:
            head_tosend = {"type": RESPONSE_SEARCH_FILE, "status": "No search results"}
            logger.info("No search results")
    
    return head_tosend


def damage_upload(head_recved, fnet, db):
    paths = head_recved["paths"]
    logger.info("Totally %d Damaged Files" % len(paths))

    models = []
    category = getModelCategory(head_recved['category'])
    for path in paths:
        feature = torch.ones(128).cpu()
        feature = tensor2str(feature)
        models.append(TBModel.TableRow( category=category,
                                        name=path["name"],
                                        type="",
                                        tags="",
                                        description=path["description"],
                                        feature=feature,
                                        data='',
                                        hash=path["path"],
                                        extend=path["extend"],
                                        trans_model=json.dumps(path["trans_model"]),
                                        trans_camera=json.dumps(path["trans_camera"])
                                        ))

    with open('config.yml', 'r') as conf_file:
        ymlConf = yaml.load(conf_file, Loader= yaml.FullLoader)
        ipfs_url = ymlConf['ipfs']['url']
    # 连接数据库
    tb_model = TBModel(database=db, feature_net=fnet, ipfs_url=ipfs_url)
    # 添加模型到数据库
    status = tb_model.upload_models(models)
    # 返回结果
    if(None != status):
        head_tosend = {"type": RESPONSE_ERROR, "status":status}
    else:
        head_tosend = {"type": RESPONSE_DAMAGE_UPLOAD, "status":''}
            
    logger.info("Damaged Files Upload Successfully!")
    
    return head_tosend